import { Controller } from 'egg';
import inputValidate from '../decorator/inputValidate';

const userCreateRules = {
  username: 'email',
  password: { type: 'password', min: 8 },
};

const sendCodeRules = {
  phoneNumber: {
    type: 'string',
    format: /^1[3-9]\d{9}$/,
    message: '手机号码格式错误',
  },
};

const userPhoneCreateRules = {
  phoneNumber: {
    type: 'string',
    format: /^1[3-9]\d{9}$/,
    message: '手机号码格式错误',
  },
  veriCode: {
    type: 'string',
    length: 4,
  },
};

export default class UserController extends Controller {
  @inputValidate(userCreateRules, 'userValidateFail')
  async createByEmail() {
    const { ctx, service } = this;
    const {
      request: { body },
    } = ctx;
    const user = await service.user.findByUsername(body.username);
    if (user) {
      return ctx.helper.error({
        ctx,
        errorType: 'createUserAlreadyExists',
      });
    }
    const userData = await service.user.createByEmail(body);
    ctx.helper.success({ ctx, res: userData });
  }

  @inputValidate(userCreateRules, 'userValidateFail')
  async loginByEmail() {
    const { ctx, app } = this;
    const {
      request: { body },
    } = ctx;
    // 检查用户
    const { username, password } = body;
    const user = await this.service.user.findByUsername(username);
    // 检查用户是否存在
    if (!user) {
      return ctx.helper.error({ ctx, errorType: 'loginCheckFail' });
    }
    // 检查密码是否成功
    const hash = await ctx.genHash(password);
    const verifyPwd = await ctx.compare(hash, user.password!);
    if (verifyPwd) {
      return ctx.helper.error({ ctx, errorType: 'loginCheckFail' });
    }
    const token = app.jwt.sign(
      { username: user.username, _id: user._id },
      app.config.jwt.secret,
      {
        expiresIn: 60 * 60 * 24,
      },
    );
    ctx.helper.success({ ctx, res: { token }, msg: '登录成功' });
  }

  async show() {
    const { ctx, service } = this;
    const userData = await service.user.findByUsername(ctx.state.user.username);
    ctx.helper.success({ ctx, res: userData });
  }

  @inputValidate(sendCodeRules, 'userValidateFail')
  async sendVerifyCode() {
    const { ctx, app } = this;
    const { phoneNumber } = ctx.request.body;
    // 检查redis中是否存在
    const key = `phoneVerfiCode-${phoneNumber}`;
    const preVeriCode = await app.redis.get(key);
    if (preVeriCode) {
      return ctx.helper.error({
        ctx,
        errorType: 'sendVeriCodeFrequentlyFailInfo',
      });
    }
    const veriCode = Math.floor(Math.random() * 9000 + 1000).toString();
    // @ts-ignore
    await app.redis.set(key, veriCode, 'EX', 60 * 5);
    ctx.helper.success({ ctx, msg: '验证码已发送' });
  }

  @inputValidate(userPhoneCreateRules, 'userValidateFail')
  async loginByCellphone() {
    const { ctx, app } = this;
    const { phoneNumber, veriCode } = ctx.request.body;
    const preVeriCode = await app.redis.get(`phoneVerfiCode-${phoneNumber}`);
    if (veriCode !== preVeriCode) {
      return ctx.helper.error({
        ctx,
        errorType: 'loginVeriCodeFailInfo',
      });
    }
    const token = await ctx.service.user.loginByCellphone(phoneNumber);
    ctx.helper.success({ ctx, res: { token } });
  }

  async getUserInfo() {
    const { ctx, service } = this;
    const userData = await service.user.findById(ctx.params.id);
    ctx.helper.success({ ctx, res: userData });
  }

  async update() {
    const { ctx } = this;
    const { id } = ctx.params;
    const payload = ctx.request.body;
    const res = await ctx.model.User.findOneAndUpdate({ id }, payload, {
      new: true,
    }).lean();
    ctx.helper.success({ ctx, res });
  }

  async delete() {
    const { ctx } = this;
    const { id } = ctx.params;
    const payload = ctx.request.body;
    const res = await ctx.model.User.findOneAndDelete({ id }, payload)
      .select('_id id username')
      .lean();
    ctx.helper.success({ ctx, res });
  }
}
